package com.demo.springcloud.service;

import cn.hutool.core.util.IdUtil;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.concurrent.TimeUnit;

/**
 * @author chenyuan
 * @date 2020/12/6 19:32
 */
@Service
public class PaymentServiceImpl implements PaymentService {
	//成功
	@Override
	public String paymentInfo_OK(Integer id) {
		return "线程池：" + Thread.currentThread().getName() + "   paymentInfo_OK,id：  " + id + "\t" + "哈哈哈";
	}

	// ========= 服务降级 =========

	//失败
	@Override
	/** 配置需要进行 FallBack 的方法 */
	@HystrixCommand(
			// fallbackMethod :出错后处理方法的方法名
			fallbackMethod = "paymentInfo_TimeOutHandler",
			// 方法设置超时时间为 2000 ms => 2 s
			// 也即该方法在给时间内执行完即正常，超过该时间则执行下面的异常方法
			commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
					value = "2000")}
	)
	public String paymentInfo_TimeOut(Integer id) {
		int timeNumber = 3;
		try {
			TimeUnit.SECONDS.sleep(timeNumber);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "线程池：" + Thread.currentThread().getName() + "   paymentInfo_TimeOut,id：  " + id + "\t" + "呜呜呜" + " 耗时(秒)" + timeNumber;
	}

	/**
	 * 上面方法的出错后的处理类
	 */
	public String paymentInfo_TimeOutHandler(Integer id) {
		return "线程池：" + Thread.currentThread().getName() + "   paymentInfo_TimeOutHandler,id：  " + id + "\t" + "/(ㄒoㄒ)/~~";
	}

	// ========= 服务熔断 =========

	private int errorTimes = 0;

	@Override
	@HystrixCommand(
			// 兜底的方法
			fallbackMethod = "paymentCircuitBreaker_fallback",
			commandProperties = {
					// 是否开启断路器
					@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
					// 请求次数，表示每 10 次请求失败率达到下面的配置失败率，则熔断
					@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
					// 时间范围
					@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
					// 失败率达到多少后跳闸，这里表示 60 %
					@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),
			})
	public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
		if (id < 0) {
			// 当传入负数，故意抛出异常
			throw new RuntimeException("*****id 不能负数");
		}
		String serialNumber = IdUtil.simpleUUID();

		errorTimes = 0;
		return Thread.currentThread().getName() + "\t" + "调用成功,流水号：" + serialNumber;
	}

	/**
	 * 异常的处理方法
	 */
	public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
		return "id 不能负数，请稍候再试,(┬＿┬)/~~     id: " + id + ", errorTimes:" + (errorTimes++);
	}
}
